package com.whz.http.client;

import com.alibaba.fastjson.JSON;
import com.whz.generic.threads.DefaultCommonThreadPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 默认的http client
 *
 * @author whz
 */
@Slf4j
public class DefaultHttpClient {
    private final ScheduledExecutorService timer =
            DefaultCommonThreadPool.DEFAULT_THREAD_POOL.scheduledExecutorService();
    private final FeignHttpClientProperties clientProperties;
    private final RequestConfig requestConfig;

    public DefaultHttpClient(final int socketTimeout, FeignHttpClientProperties clientProperties) {
        this.clientProperties = clientProperties;
        // tcp 配置
        requestConfig = RequestConfig.custom()
                                     .setSocketTimeout(socketTimeout)
                                     .setConnectTimeout(clientProperties.getConnectionTimeout())
                                     .setCircularRedirectsAllowed(clientProperties.isFollowRedirects())
                                     .setConnectionRequestTimeout(clientProperties.getConnectionTimeout())
                                     .setContentCompressionEnabled(true)
                                     .build();

        log.info("===== creating Tongyu closeableHttpClient:\n  ====== RequestConfig is :    \n{}",
                 JSON.toJSONString(requestConfig));
    }


    /**
     * 连接池
     */
    public HttpClientConnectionManager buildPoolManager(final FeignHttpClientProperties clientProperties) {
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(
                clientProperties.getTimeToLive(),
                clientProperties.getTimeToLiveUnit()
        );
        // 总连接数
        manager.setMaxTotal(clientProperties.getMaxConnections());
        // 同路由的并发数
        manager.setDefaultMaxPerRoute(clientProperties.getMaxConnectionsPerRoute());
        // 定时清理连接池
        cleanPoolFixRate(manager);

        return manager;
    }

    private void cleanPoolFixRate(final HttpClientConnectionManager manager) {
        // 启动定时器，定时回收过期的连接
        timer.scheduleAtFixedRate(() -> {
                                      manager.closeExpiredConnections();
                                      manager.closeIdleConnections(
                                              clientProperties.getTimeToLive(),
                                              clientProperties.getTimeToLiveUnit()
                                      );
                                  },
                                  TimeUnit.MINUTES.toMillis(3),
                                  clientProperties.getConnectionTimerRepeat(),
                                  TimeUnit.MICROSECONDS);
        log.info("===== creating Tongyu closeableHttpClient 定时清理连接池 ===");
    }

    public CloseableHttpClient client() {
        return HttpClientBuilder.create()
                                .disableCookieManagement()
                                .useSystemProperties()
                                .setConnectionManager(buildPoolManager(clientProperties))
                                .setDefaultRequestConfig(requestConfig)
                                .build();
    }
}